#include "customscroll.h"
#include <QMouseEvent>
#include <QDebug>
#include <QApplication>
#include <QPainter>
#include <QTableWidget>
#include <QHeaderView>
#include <QScrollBar>
#include <QAbstractAnimation>


CustomScroll::CustomScroll(QTableView* table,QWidget *parent) :
    QWidget(parent)
    ,m_dragFlag(MOUSE_RELEASE)
{
    setAttribute(Qt::WA_TranslucentBackground);

    m_scrollBar = table->verticalScrollBar();
    m_scrollBar->hide();
    connect(m_scrollBar,&QScrollBar::sliderPressed,[=](){ m_scrollTimer.stop(); });           //按下滚动条
    connect(m_scrollBar,&QScrollBar::sliderMoved,[=](){ m_scrollTimer.stop(); });
    connect(m_scrollBar,&QScrollBar::sliderReleased,[=](){ m_scrollTimer.start(SCROL_SHOW_TIME); });     //松开滚动条

    animation = new QPropertyAnimation(m_scrollBar,"value",this);       //创建动画对象
    connect(animation,&QPropertyAnimation::finished,[=](){  m_scrollTimer.start(SCROL_SHOW_TIME); });  //动画结束后启动定时器准备隐藏滚动条
    connect(&m_scrollTimer,SIGNAL(timeout()),this,SLOT(scrollTimeOut()));

    m_table = table;
    m_table->viewport()->installEventFilter(this);  //安装事件过滤器
    m_table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);

    this->resize(SCROL_WIDTH,m_table->height());
    this->move(0,5);    //将滑动条移至最右侧
    this->raise();      //置顶父窗口
    m_srcollH  = m_table->height();
}

void CustomScroll::scrollTimeOut()
{
    m_scrollBar->hide();
    m_dragFlag = MOUSE_RELEASE;
}

//bool CustomScroll::eventFilter(QObject *obj, QEvent *evt)
//{
//    static int pressPoint_y   = 0;      //记录按下位置
//    static int dragPoint_y    = -1;     //拖动位置
//    static qint64 pressMSec ;           //记录按下的时间点

//    int scrollV_max = m_scrollBar->maximum ();
//    int scrollV_min = m_scrollBar->minimum ();

//    QMouseEvent *mouse =  dynamic_cast<QMouseEvent *>(evt);
//    if(mouse)
//    {
//        //=================== 按下 ===========================
//        if( mouse->type() ==QEvent::MouseButtonPress)
//        {
//            m_scrollTimer.stop();
//            m_scrollBar->show();

//            pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch();     //记录按下的时间
//            dragPoint_y  = mouse->pos().y();               //当前坐标
//            pressPoint_y = dragPoint_y;                      //按下的位置

//            animation->stop();
//            m_selectRow = m_table->indexAt(mouse->pos()).row();    //选择当前行
//            m_dragFlag = MOUSE_PRESS;
//        }
//        //======================= 只点击了一下屏幕，未移动 =============================
//        else if(mouse->type() == QEvent::MouseButtonRelease && m_dragFlag == MOUSE_PRESS)
//        {
//            m_dragFlag = MOUSE_RELEASE;
//            m_scrollTimer.start(SCROL_SHOW_TIME);  //2S后取消滑动条显示
//            m_scrollBar->show();
//        }
//        //==================== 鼠标移动 ==============================
//        else if((m_dragFlag!= MOUSE_RELEASE) && mouse->type() == QEvent::MouseMove)
//        {
//            if(m_dragFlag == MOUSE_PRESS)     //鼠标按下到现在的滑动状态，即表示首次滑动
//            {
//                if(qAbs(dragPoint_y - mouse->pos().y()) < 5)   //判断移动阀值,避免误操作
//                    return true;
//                else
//                {
//                   m_dragFlag = MOUSE_PRESS_MOVE;           //转为移动状态
//                   m_table->clearSelection();               //已经移动了,所以取消之前的选择
//                   dragPoint_y = mouse->pos().y();          //获取当前坐标
//                   return true;
//                }
//            }
//            int moveValue = (dragPoint_y - mouse->pos().y()) + m_scrollBar->value(); //移动值 + 滚动条当前值 = 滑动到的位置
//            dragPoint_y = mouse->pos().y();

//            m_table->clearSelection();
//            if(scrollV_min > moveValue) moveValue = scrollV_min;    //添加位置限制
//            if(moveValue > scrollV_max) moveValue = scrollV_max;
//            m_scrollBar->setValue(moveValue);   //表格显示到对应位置
//        }
//        //======================= 从按下滑动状态 到现在 鼠标松开，惯性滑动 =============================
//        else if(m_dragFlag == MOUSE_PRESS_MOVE && mouse->type() == QEvent::MouseButtonRelease)
//        {
//            dragPoint_y = -1;
//            int releasePoint_y = mouse->pos().y();

//            int ms= QDateTime::currentDateTime().toMSecsSinceEpoch()-pressMSec;
//            int Pixel_per_second=qAbs(releasePoint_y - pressPoint_y)*1000/ms;       //计算每秒像素点

//            if(Pixel_per_second < 300 || qAbs(releasePoint_y - pressPoint_y) < 45)
//            {
//                m_dragFlag = MOUSE_RELEASE;
//                return true;
//            }
//            else
//            {
//                int moveValue;
//                if(ms > 1000)      //滑动的时间不能超过1s
//                {
//                     m_dragFlag = MOUSE_RELEASE;
//                     return true;
//                }
//                //计算滑动得到的位置
//                if(releasePoint_y - pressPoint_y > 0)     //向下滑动
//                {
//                    moveValue = m_scrollBar->value() - Pixel_per_second*0.2*(300/ms);   //滑动时间越长,moveValue值越小,因为不是快速滑动
//                    if(moveValue < scrollV_min)
//                        moveValue = scrollV_min;
//                }
//                else
//                {
//                    moveValue = m_scrollBar->value() + Pixel_per_second*0.2*(300/ms);
//                    if(moveValue > scrollV_max)
//                        moveValue = scrollV_max;
//                }
//                m_table->clearSelection();
//                //滑动松开后惯性滑动动画
//                animation->setDuration(2000-ms);
//                animation->setEndValue(moveValue);
//                animation->setEasingCurve(QEasingCurve::OutQuart);
//                animation->start();
//                m_dragFlag = MOUSE_RELEASE_MOVE;    //鼠标松开，惯性滑动状态
//            }
//        }
//    }
//    return QWidget::eventFilter(obj,evt);
//}


bool CustomScroll::eventFilter(QObject *obj, QEvent *evt)
{
    // ======== 物理仿真量 ========
    static float speed = 0;   //速度 单位：像素/s
    static int pos,lastPos = 0;       //位置  单位：像素
    static float drag = 0.1;    //阻力大小，值越大，减速越快

    static QPoint lastPoint;    //上次鼠标点记录
    static uint lastTime;       //上次迭代时间

    static float maxSpeed = 1000;    //速度限制

    //位置限制
    int maxPos = m_scrollBar->maximum ();
    int minPos = m_scrollBar->minimum ();

    //===== 1、更新当前量 =====
    int currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
    QPoint currentPoint = mouse->pos();

    //===== 2、计算速度 =====
    QMouseEvent *mouse =  dynamic_cast<QMouseEvent *>(evt);
    if( mouse->type() ==QEvent::MouseButtonPress)   //按下拖动情况
    {
        speed = (currentPoint.y() - lastPoint.y())*1000/(currentTime - lastTime); // 单位：像素/s
        if(speed > maxSpeed)    speed = maxSpeed;
    }
    else
    {
        if(fabs(speed) <= drag*2)  speed = 0;//如果已经停止，则不需要计算速度了
        else
        {   //更新速度 -- 矢量，带方向
            if(speed > 0)   speed -= drag;
            else            speed += drag;
        }
    }
    //===== 3、计算位置 =====
    pos = lastPos + speed * (currentTime - lastTime)/1000;  //更新位置
    if(pos > maxPos)    pos = maxPos;
    if(pos < minPos)    pos = minPos;

    //===== 4、更新下次迭代量 =====
    lastTime = currentTime;
    lastPoint = currentPoint;
    lastPos = pos;

    //===== 5、更新UI =====
    m_scrollBar->setValue(pos);

    return QWidget::eventFilter(obj,evt);
}

